package com.rex.saas.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.rex.saas.bean.BaseResponse;
import com.rex.saas.bean.DeviceBasicData;
import com.rex.saas.bean.LatestOtaResponse;
import com.rex.saas.bean.ResultCode;
import com.rex.saas.bean.request.AddOtaInfoRequest;
import com.rex.saas.bean.request.UpdateDevOtaRequest;
import com.rex.saas.bean.response.OtaStatusResponse;
import com.rex.saas.constants.Constants;
import com.rex.saas.db.entity.SaasDeviceInfo;
import com.rex.saas.db.entity.SaasOtaInfo;
import com.rex.saas.enums.OtaTypeEnum;
import com.rex.saas.service.DeviceService;
import com.rex.saas.service.OtaService;
import com.rex.saas.service.RexolarApiClient;
import com.rex.saas.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * @ClassName OtaController
 * @Description:
 * @Author: zhusiyu
 */
@RestController
@Slf4j
@RequestMapping("/ota")
public class OtaController {
    @Autowired
    private OtaService otaService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    RexolarApiClient rexolarApiClient;

    @GetMapping("/list")
    public BaseResponse list() {
        return BaseResponse.ok();
    }

    @PostMapping("/add")
    public BaseResponse add(HttpServletRequest request, @RequestBody AddOtaInfoRequest addOtaInfoRequest) {
        log.info("addOtaInfoRequest:{}", addOtaInfoRequest);
        String token = request.getHeader("token");
        String tenantId = JwtUtils.getTenantId(token);
        if(StringUtils.isBlank(tenantId)){
            log.error("add tenantId is null,spaceInfoId:{}", tenantId);
            return BaseResponse.error("token异常", ResultCode.PARAM_ERROR);
        }
        List<String> roles = JwtUtils.getRole(token);
        if (!roles.contains(Constants.TENANT_ADMIN)){
            log.error("ota add, user has not permission , addOtaInfoRequest:{}", addOtaInfoRequest);
            return BaseResponse.error("用户没有权限", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(addOtaInfoRequest.getCategoryName())){
            log.error("addOtaInfoRequest categoryName is null, addOtaInfoRequest:{}", addOtaInfoRequest);
            return BaseResponse.error("categoryName参数为空", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(addOtaInfoRequest.getVersion())){
            log.error("addOtaInfoRequest version is null, addOtaInfoRequest:{}", addOtaInfoRequest);
            return BaseResponse.error("version参数为空", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(addOtaInfoRequest.getSize())){
            log.error("addOtaInfoRequest size is null, addOtaInfoRequest:{}", addOtaInfoRequest);
            return BaseResponse.error("size参数为空", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(addOtaInfoRequest.getDownloadUrl())){
            log.error("addOtaInfoRequest downloadUrl is null, addOtaInfoRequest:{}", addOtaInfoRequest);
            return BaseResponse.error("downloadUrl参数为空", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(addOtaInfoRequest.getMd5())){
            log.error("addOtaInfoRequest md5 is null, addOtaInfoRequest:{}", addOtaInfoRequest);
            return BaseResponse.error("md5参数为空", ResultCode.PARAM_ERROR);
        }
        List<SaasOtaInfo> list = otaService.queryOtaInfoByName(addOtaInfoRequest.getCategoryName(),
                addOtaInfoRequest.getModelId(),addOtaInfoRequest.getVersion(), tenantId);
        if(CollectionUtils.isNotEmpty(list)){
            log.error("addOtaInfoRequest name is exist, addOtaInfoRequest:{}", addOtaInfoRequest);
            return BaseResponse.error("该版本ota固件已经存在", ResultCode.PARAM_ERROR);
        }

        return BaseResponse.ok(otaService.addOtaInfo(addOtaInfoRequest, tenantId));
    }
    @GetMapping("/latest")
    public BaseResponse latest(HttpServletRequest request, @RequestParam String categoryName, @RequestParam String modelId,
                               @RequestParam(name = "type", defaultValue = "0", required = false) Integer type) {
        log.info("latest categoryName:{}, modelId:{}, type:{}", categoryName, modelId, type);
        String token = request.getHeader("token");
        String tenantId = JwtUtils.getTenantId(token);
        if(StringUtils.isBlank(tenantId)){
            log.error("latest tenantId is null,spaceInfoId:{}", tenantId);
            return BaseResponse.error("token异常", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(categoryName)){
            log.error("latest categoryName is null, gwName:{}", categoryName);
            return BaseResponse.error("类别名称参数为空", ResultCode.PARAM_ERROR);
        }
        SaasOtaInfo latest = otaService.latest(categoryName, modelId, type);
        if(latest==null){
            log.error("latest is null, categoryName:{}", categoryName);
            return BaseResponse.error("没有查询到固件版本，", ResultCode.PARAM_ERROR);
        }
        LatestOtaResponse lastOtaResponse = new LatestOtaResponse();
        BeanUtils.copyProperties(latest, lastOtaResponse);
        return BaseResponse.ok(lastOtaResponse);
    }

    @PostMapping("/updateDevice")
    public BaseResponse updateDevice(HttpServletRequest request, @RequestBody UpdateDevOtaRequest updateDevOtaRequest) {
        log.info("updateDevice updateDevOtaRequest:{}", updateDevOtaRequest);
        String token = request.getHeader("token");
        String tenantId = JwtUtils.getTenantId(token);
        if(StringUtils.isBlank(tenantId)){
            log.error("updateDevice tenantId is null,spaceInfoId:{}", tenantId);
            return BaseResponse.error("token异常", ResultCode.PARAM_ERROR);
        }

        if (CollectionUtils.isEmpty(updateDevOtaRequest.getDeviceNames())){
            log.error("updateDevice deviceNames is null, updateDevOtaRequest:{}", updateDevOtaRequest);
            return BaseResponse.error("设备列表不能为空", ResultCode.PARAM_ERROR);
        }
        if(updateDevOtaRequest.getType()==null){
            log.error("updateDevice type is null, updateDevOtaRequest:{}", updateDevOtaRequest);
            return BaseResponse.error("设备类型不能为空", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(updateDevOtaRequest.getVersion())){
            log.error("updateDevice version is null, updateDevOtaRequest:{}", updateDevOtaRequest);
            return BaseResponse.error("版本号不能为空", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isBlank(updateDevOtaRequest.getCategoryName())){
            log.error("updateDevice categoryName is null, updateDevOtaRequest:{}", updateDevOtaRequest);
            return BaseResponse.error("下载地址不能为空", ResultCode.PARAM_ERROR);
        }
        List<SaasOtaInfo> otaList = otaService.queryOtaInfoByName(updateDevOtaRequest.getCategoryName(),
                updateDevOtaRequest.getModelId(), updateDevOtaRequest.getVersion(), tenantId);
        if(CollectionUtils.isEmpty(otaList)){
            log.error("updateDevice ota is not exist, updateDevOtaRequest:{}", updateDevOtaRequest);
            return BaseResponse.error("ota不存在", ResultCode.PARAM_ERROR);
        }
        if(otaList.size()>1){
            log.error("updateDevice ota size > 1 exist, updateDevOtaRequest:{}", updateDevOtaRequest);
            return BaseResponse.error("ota存在多份请检查", ResultCode.PARAM_ERROR);
        }

        List<String> roles = JwtUtils.getRole(token);
        if (!roles.contains(Constants.TENANT_ADMIN)){
            for(String deviceName:updateDevOtaRequest.getDeviceNames()){
                SaasDeviceInfo deviceInfo = deviceService.getDeviceByName(deviceName, tenantId);
                if(deviceInfo==null){
                    log.error("updateDevice deviceInfo is null, updateDevOtaRequest:{}", updateDevOtaRequest);
                    return BaseResponse.error("设备不存在", ResultCode.PARAM_ERROR);
                }
                if(!JwtUtils.getCustomerId(token).equals(deviceInfo.getCustomerId())){
                    log.error("updateDevice customerId not match error, updateDevOtaRequest:{}", updateDevOtaRequest);
                    return BaseResponse.error("用户没有设备权限"+deviceName, ResultCode.PARAM_ERROR);
                }
            }
        }

        String tenantToken = rexolarApiClient.getTenantToken(tenantId);
        if (updateDevOtaRequest.getType()== OtaTypeEnum.GW_OTA.getCode()){
           boolean flag = otaService.updateGwOta(updateDevOtaRequest.getDeviceNames(), otaList.get(0), tenantToken);
            if(!flag){
                log.error("updateDevice updateGwOta is error, updateDevOtaRequest:{}", updateDevOtaRequest);
                return BaseResponse.error("升级失败", ResultCode.PARAM_ERROR);
            }
        }else if (updateDevOtaRequest.getType()==OtaTypeEnum.SUB_OTA.getCode()){
            boolean flag = otaService.updateSubDeviceOta(updateDevOtaRequest.getDeviceNames(), otaList.get(0), tenantToken);
            if(!flag){
                log.error("updateDevice updateSubDeviceOta is error, updateDevOtaRequest:{}", updateDevOtaRequest);
                return BaseResponse.error("升级失败", ResultCode.PARAM_ERROR);
            }
        }else if(updateDevOtaRequest.getType()==OtaTypeEnum.DEVICE_OTA.getCode()){
            boolean flag = otaService.updateDeviceOta(updateDevOtaRequest.getDeviceNames(), otaList.get(0), tenantToken);
            if(!flag){
                log.error("updateDevice updateDeviceOta is error, updateDevOtaRequest:{}", updateDevOtaRequest);
                return BaseResponse.error("升级失败", ResultCode.PARAM_ERROR);
            }
        }else {
            log.error("updateDevice type is not exist, updateDevOtaRequest:{}", updateDevOtaRequest);
            return BaseResponse.error("设备类型不存在", ResultCode.PARAM_ERROR);
        }
        return BaseResponse.ok(true);
    }
    @GetMapping("/otaStatus")
    public BaseResponse otaStatus(HttpServletRequest request, @RequestParam String deviceName) {
        log.info("otaStatus deviceName:{}", deviceName);
        String token = request.getHeader("token");
        String tenantId = JwtUtils.getTenantId(token);
        if(StringUtils.isBlank(tenantId)){
            log.error("otaStatus tenantId is null,spaceInfoId:{}", tenantId);
            return BaseResponse.error("token异常", ResultCode.PARAM_ERROR);
        }
        SaasDeviceInfo saasDeviceInfo = deviceService.getDeviceByName(deviceName, JwtUtils.getTenantId(token));
        if(saasDeviceInfo==null){
            log.error("otaStatus deviceName is not exist, deviceName:{}", deviceName);
            return BaseResponse.error("设备不存在", ResultCode.PARAM_ERROR);
        }
        List<String> roles = JwtUtils.getRole(token);
        if (!roles.contains(Constants.TENANT_ADMIN)){
            if(!JwtUtils.getCustomerId(token).equals(saasDeviceInfo.getCustomerId())){
                log.error("otaStatus customerId not match error, deviceName:{}", deviceName);
                return BaseResponse.error("用户没有设备权限"+deviceName, ResultCode.PARAM_ERROR);
            }
        }
        String tenantToken = rexolarApiClient.getTenantToken(tenantId);
        DeviceBasicData deviceBasicData =  rexolarApiClient.getDeviceByDeviceName(deviceName, tenantToken);
        if(deviceBasicData==null){
            log.error("updateDevice core deviceName is not exist, deviceName:{}", deviceName);
            return BaseResponse.error("设备不存在", ResultCode.PARAM_ERROR);
        }
        Map<String,Object> attributes = rexolarApiClient.getDeviceAttributes(deviceBasicData.getCoreId(), tenantToken, new String[]{"OtaResult"});
        OtaStatusResponse otaStatusResponse = new OtaStatusResponse();
        otaStatusResponse.setDeviceName(deviceName);
        if (!CollectionUtils.isEmpty(attributes) && attributes.get("OtaResult")!=null){
            Map<String,Object> otaResult = (Map) attributes.get("OtaResult");
            otaStatusResponse.setType(otaResult.get("Type")==null?null:otaResult.get("Type").toString());
            otaStatusResponse.setOtaStatus(otaResult.get("Status")==null?"":otaResult.get("Status").toString());
            otaStatusResponse.setProgress(otaResult.get("Progress")==null?"":otaResult.get("Progress").toString());
        }else{
            otaStatusResponse.setOtaStatus("-1");
            otaStatusResponse.setProgress("0");
        }
        return BaseResponse.ok(otaStatusResponse);
    }
}
